@model WalkingTec.Mvvm.Core.BaseVM
<p>BaseVM is the basic VM in the WTM framework. All built-in VMs in the framework inherit from it. At the same time, the framework requires that all VMs customized by developers inherit from it.</p>
<br />
<wt:quote>
    BaseVM provides a place for developers to write logic by connecting controller and view. If you need to add, delete, modify, query, import or export data, please inherit from more specific VM
</wt:quote>
<wt:fieldset field-set-style="Simple" title="Build a VM">
    <p>It's very simple to build a basic VM. You only need to inherit the BaseVM. In the following sample, we will build a LoginVM to handle user login operations.</p>
    <wt:code title="LoginVM.cs">
using WalkingTec.Mvvm.Core;

public class LoginVM : BaseVM{

}
    </wt:code>
    <p>The above code defines a LoginVM. What's the use of it?</p>
    <p>In short, when you create this VM in the Controller through the CreateVM method, the framework will automatically transfer a lot of data needed for writing logic to the VM, such as the information of the current login user, the information of form submission, the current database connection, etc</p>
    <p>At the same time, the properties in VM can also be used to bind the front-end page controls. VM connects the front-end, back-end and database. In VM, you can access all the required information to write the logic you need.</p>
    <p>Let's improve LoginVM, below is a demonstration of a simple login operation</p>
    <wt:code title="LoginVM.cs">
using WalkingTec.Mvvm.Core;

public class LoginVM : BaseVM{

    [Display( Name = "Account")]
    [Required( AllowEmptyStrings = false)]
    [StringLength(10)]
    public string Username { get; set; }

    [Display( Name = "Password")]
    [Required( AllowEmptyStrings = false)]
    [StringLength(10, ErrorMessage = "{0} has maximun {1} characters")]
    public string Password { get; set; }

    public LoginUserInfo DoLogin()
    {
        //use itcode and password to query a user
        var user = DC.Set&lt;FrameworkUserBase&gt;()
            .Where(x =&gt; x.ITCode.ToLower() == ITCode.ToLower() && x.Password.ToLower() == Password.ToLower() && x.IsValid == true)
            .SingleOrDefault();
            //output error if not found
            if (user == null)
            {
                MSD.AddModelError("", "Login failed");
            }
        return user;
    }
}
    </wt:code>

</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="Using VM">
    <p>We encapsulate all the login logic in LoginVM, therefore our code is kept at minimum in a controller.</p>
    <wt:code title="LoginController.cs">
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;

[Public]
public class LoginController : BaseController
{
    [ActionDescription("Login")]
    public IActionResult Login()
    {
        LoginVM vm = CreateVM&lt;LoginVM&gt;();
        return View(vm);
    }

    [HttpPost]
    public ActionResult Login(LoginVM vm)
    {
        var user = vm.DoLogin();
        if (user == null)
        {
            return View(vm);
        }
        else
        {
            return Redirect("/home/index");
        }
    }
}
    </wt:code>

    <wt:quote>
        Basecontroller is the Controller base class provided by the WTM. All application controllers should inherit from this class. For details, please refer to the Controller documentation.<br />
        [Public],[ActionDescription][Public],[ActionDescription]and other attributes are provided by the framework and applied to the controller and action. Please refer to the Controller documenation for details.<br />
        In the Controller, CreateVM is used to initialize VM, by doing this we can pass a lot of information of current request to VM, such as database connection, session, etc.
    </wt:quote>

</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="Custom validation of VM">
    <p>Simple single field validation can be achieved by adding Attribute to VM models</p>
    <p>Complex validation logic can be added by overriding Validate method in BaseVM</p>
    <p>The following code demonstrates a VM that validates a password:</p>
    <wt:code title="ChangePasswordVM.cs">
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using WalkingTec.Mvvm.Core;

namespace WalkingTec.Mvvm.Demo.ViewModels.HomeVMs
{
    public class ChangePasswordVM : BaseVM
    {
        [Display(Name = "Account")]
        public string ITCode { get; set; }

        [Display(Name = "Current password")]
        [Required(AllowEmptyStrings = false)]
        [StringLength(50, ErrorMessage = "{0} has maximun {1} characters")]
        public string OldPassword { get; set; }

        [Display(Name = "New password")]
        [Required(AllowEmptyStrings = false)]
        [StringLength(50, ErrorMessage = "{0} has maximun {1} characters")]
        public string NewPassword { get; set; }

        [Display(Name = "Comfirm password")]
        [Required(AllowEmptyStrings = false)]
        [StringLength(50, ErrorMessage = "{0} has maximun {1} characters")]
        public string NewPasswordComfirm { get; set; }

        public override void Validate()
        {
            //check if the current password is correct
            if (DC.Set&lt;FrameworkUserBase&gt;()
      .Where(x =&gt; x.ITCode == LoginUserInfo.ITCode && x.Password == Utils.GetMD5String(OldPassword))
      .SingleOrDefault() == null){
                MSD.AddModelError( "OldPassword", "The current password is wrong");
            }
            //check if the new password and password comfirm are the same
            if ( NewPassword != NewPasswordComfirm )
            {
                MSD.AddModelError( "NewPasswordComfirm", "The new password and password comfirm are not the same");
            }
        }

        public void DoChange()
        {
            var user = DC.Set&lt;FrameworkUserBase&gt;().Where(x =&gt; x.ITCode == LoginUserInfo.ITCode).SingleOrDefault();
            if (user != null)
            {
                user.Password = Utils.GetMD5String(NewPassword);
            }
            DC.SaveChanges();
        }
    }
}
    </wt:code>
</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="VM initialization">
    <p>Rewrite InitVM and ReInitVM methods in VM to perform variables and operations that need to be initialized for VM. The reason for putting the initialization code here is that only after InitVM and ReInitVM, DataContext,Session,ModelState in VM have values.</p>
    <p>InitVMis is called when creating VM, ReInitVM is called when model validation fails when post returns. If ReInitVMmethod is not overridden, InitVM method will be called by default.</p>
    <p>When the a VM is established manually through new, InitVM and / or ReInitVM need to be called manually, and the CopyContext method is used to copy the DataContext, Session and modelModelStat from other VM.</p>
</wt:fieldset>
    <script>
    layui.use('code',function(){layui.code({ about: false })})
    </script>
<script>
  $("#@Model.ViewDivId").parent().css("height", "auto");
</script>
